home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
qlib205.zip
/
QLIB.ZIP
/
SRC
/
QLIB
/
PACK.ASM
< prev
next >
Wrap
Assembly Source File
|
1997-03-20
|
11KB
|
594 lines
;this is part of file i/o
;for packed file loading/etc.
.data?
align 4
pts dd ? ;table size
phs dd ? ;handles size
old_int21h df ? ;old int21h handler
coff dd ? ;current file offset (within the pack file)
csiz dd ? ;current file size
cpos dd ? ;current file position (0=starting pos)
cend dd ? ;coff + csiz
fn db 13 dup (?) ;File name used by _open
ps struct
fn db 13 dup (?) ;the name
fh dw ? ;the handle (not used in the header when in the file)
off dd ? ;offset in the file
siz dd ? ;size of file
ps ends
.data
pt dd 0 ;the tables (malloc'ed)
;this holds the struct of each file loaded (within the pack files)
ph dd 0 ;Packs Handles (malloc'ed) FIX : v2.01 : No longer restricted to 16
;this holds the handles of each pack file loaded to quickly know when
; file IO is being performed on a pack file
pack_on db 0 ;is packed file init?
chand dw 0 ;current handle (0=none!) (if one file is opened then
; another cannot be opened!)
temp4 dd 0 ;used all over
noff dd 0 ;# of files (this must come right after temp4)
.code
readpack proc private,h:word,buf:dword,len:dword
mov ah,3fh
mov bx,h
mov ecx,len
mov edx,buf
pushfd
call [old_int21h]
ret
readpack endp
closepack proc private,h:word
mov bx,h
mov ah,3eh
pushfd
call [old_int21h]
ret
closepack endp
openpack proc private,nam:dword,acc:byte
mov edx,nam
mov ah,3dh
mov al,acc
pushfd
call [old_int21h]
ret
openpack endp
pack_init proc,siz:word,packs:word
;siz=# of entries(files)alloced for
;packs=# of pack files that can be opened
pushad ;FIX : v2.01
.if pack_on ;already installed?
jmp bad
.endif
xor eax,eax
mov ax,siz
mov pts,eax
mov ebx,sizeof ps
mul ebx
mov ecx,eax
invoke malloc,eax
cmp eax,NULL
jnz @f
bad:
.if pt
callp free,pt
mov pt,0
.endif
.if ph
callp free,ph
mov ph,0
.endif
popad
mov errno,ENOMEM
mov eax,ERROR
ret
@@:
mov pt,eax
mov edi,eax
xor al,al
rep stosb ;clear table
xor eax,eax
mov ax,packs
mov phs,eax
shl eax,1
mov ecx,eax
callp malloc,eax
cmp eax,NULL
jz bad
mov ph,eax
mov edi,eax
xor al,al
rep stosb ;clear table
mov pack_on,1
callp getint,21h
mov word ptr[old_int21h+4],ax
mov dword ptr[old_int21h],edx
mov ax,selcode
mov edx,offset int_21h
callp setint,21h,ax,edx
popad
xor eax,eax ;FIX : v2.01
ret
pack_init endp
;it is not necessary to call this during exit()
pack_uninit proc uses esi ecx
.if !pack_on
mov eax,ERROR
ret
.endif
;restore oringinal DOS INT 21h handler
mov ax,word ptr[old_int21h+4]
mov edx,dword ptr[old_int21h]
callp setint,21h,ax,edx
;close all files used
mov esi,ph
mov ecx,phs
@@:
cmp wptr[esi],0
.if !zero?
callp close,wptr[edi]
.endif
add esi,2
dec ecx
jnz @b
;free buffers
callp free,pt
mov pt,0
callp free,ph
mov ph,0
mov pack_on,0
xor eax,eax
ret
pack_uninit endp
open_pack proc private,hdr:dword,h:word
mov esi,hdr
mov ebx,noff
mov edi,pt
mov edx,pts
mov ax,h
@@:
cmp bptr[edi],0
jz add1file
add edi,sizeof ps
dec edx
jnz @b
mov eax,ERROR ;not enough room to load all files
ret
add1file:
mov [esi].ps.fh,ax
mov ecx,sizeof ps
rep movsb
dec edx
dec ebx
jnz @b
xor eax,eax ;all loaded it
ret
open_pack endp
pack_open proc,strg:dword ;opens a packed file
local h:word,buf:dword
pushad ;FIX : v2.01
;look for an empty location in ph
mov ecx,phs
xor eax,eax
mov edi,ph
repnz scasw
.if !zero?
;non-found
jmp bad
.endif
;found one!
sub edi,2 ;edi=>open location
callp openpack,strg,0 ;for reading only! (objections?)
cmp eax,ERROR
jnz @f
bad:
popad
mov eax,ERROR
ret
@@:
stosw ;save handle
mov h,ax
;now to read in the files (can't use READ cause it will screw it up)
callp readpack,ax,offset temp4,6
.if eax!=6
callp closepack,h
jmp bad
.endif
mov ebx,offset temp4
cmp dword ptr[ebx],01a4b4150h ;'PAK',26
.if !zero?
callp closepack,h
jmp bad
.endif
xor eax,eax
mov eax,noff
mov ebx,sizeof ps
mul ebx
mov ecx,eax ;siz (save for l8r)
callp malloc,eax ;a temp buffer needed to quickly load all structs
.if eax==ERROR
callp closepack,h
jmp bad
.endif
mov buf,eax
callp readpack,h,buf,ecx
callp open_pack,buf,h
mov ebx,eax ;save eax...
callp free,buf ;release temp buffer
.if ebx ;...for here
callp closepack,h
popad
mov eax,ERROR
ret
.endif
popad
xor eax,eax
mov ax,h
ret
pack_open endp
;ADDED : v2.01
;opens a packed file (with header already loaded)
;these pack files must have been created with the -h option with PACKIT.EXE
pack_open_hdr proc,strg:dword,hdr:dword
local h:word
pushad
;look for an empty location in ph
mov ecx,phs
xor eax,eax
mov edi,ph
repnz scasw
.if !zero?
;non-found
jmp bad
.endif
;found one!
sub edi,2 ;edi=>open location
callp openpack,strg,0 ;for reading only
cmp eax,ERROR
jnz @f
bad:
popad
mov eax,ERROR
ret
@@:
stosw ;save handle
mov h,ax
;now to read in the files
callp readpack,ax,offset temp4,4
.if eax!=4
callp closepack,h
jmp bad
.endif
mov ebx,offset temp4
cmp dword ptr[ebx],01a484150h ;'PAH',26 ;note: it's PAH for Pack files without headers
.if !zero?
callp closepack,h
jmp bad
.endif
xor eax,eax
mov ebx,hdr
mov ax,[ebx]
mov wptr[noff],ax
mov eax,hdr
add eax,2 ;skip # of files
callp open_pack,eax,h
.if eax
popad
mov eax,ERROR
ret
.endif
popad
xor eax,eax
mov ax,h
ret
pack_open_hdr endp
align 4
pack_close proc,h:word
pushad
mov ax,h
mov esi,pt
mov ecx,pts
@@:
cmp [esi].ps.fh,ax
.if zero?
mov bptr[esi],0 ;erase filename (empty it)
.endif
add esi,sizeof ps
dec ecx
jnz @b
callp closepack,ax
mov edi,ph
mov ecx,phs
mov ax,h
repnz scasw
.if zero?
mov wptr[edi-2],0
popad
xor eax,eax
ret
.endif
popad
mov eax,ERROR
ret
pack_close endp
align 4
int_21h:
push ds
mov ds,cs:seldata
cmp pack_on,0
jz do_dos
cmp ah,3dh
jz _open
cmp ah,3eh
jz _close
cmp ah,3fh
jz _read
cmp ah,42h
jz _lseek
do_dos:
pop ds
jmp cs:[old_int21h]
_open:
;search in tables
cmp chand,0
jnz do_dos ;other handle already open!
pushad
push es
mov es,cs:seldata
mov esi,edx ;strg
mov edi,offset fn
xor ecx,ecx
cld
@@: ;capatalize the string
lodsb
cmp al,0
jz @f
cmp al,'\'
jz notfound
cmp al,':'
jz notfound
.if ((al>='a')&&(al<='z'))
sub al,32
.endif
stosb
inc ecx
.if ecx>12
jmp notfound
.endif
jmp @b
@@:
.if bptr[edi-1]=='.'
mov bptr[edi-1],0
.else
xor al,al
stosb
.endif
mov ebx,pt
mov ecx,pts
mov eax,sizeof ps
mul ecx
mov edx,offset fn
add ebx,eax
sub ebx,sizeof ps ;ptrs to last entry (so last occurance of file be used instead)
@@:
cmp bptr[ebx],0
.if !zero?
callp strcmp,edx,ebx
cmp al,0
jz found
.endif
sub ebx,sizeof ps ;search thru list backwards!!!
dec ecx
jnz @b
notfound:
pop es
popad
jmp do_dos
found:
;pack file found!
mov ax,[ebx].ps.fh ;handle
mov edx,[ebx].ps.off ;offset
mov ecx,[ebx].ps.siz ;size
mov coff,edx
mov cend,edx
mov chand,ax
mov cpos,0
mov csiz,ecx
add cend,ecx
mov ecx,edx
shr ecx,16 ;CX:DX
mov bx,ax
mov ax,4200h
; callp lseek,ax,ecx,SEEK_SET
;can't use this here, LSEEK will override and cause relative seek
pushfd
call [old_int21h]
.if carry?
;error
pop es
popad
pop ds
or byte ptr[esp+8],1 ;set carry on error
; flags , cs , eip
iretd
.endif
;successful
pop es
popad
pop ds
and byte ptr[esp+8],0feh ;clear carry
; flags , cs , eip
mov ax,cs:chand
iretd
_close:
;bx=hand
pushad
mov ax,bx
mov esi,ph ;handlers in use
mov ecx,phs
@@:
cmp [esi],ax
jz @f
add esi,2
dec ecx
jnz @b
popad
jmp do_dos
@@:
popad
mov chand,0 ;Forget about this thing ßeta V0.03
pop ds
and byte ptr[esp+8],0feh ;clear carry
; ret,cs,flags
iretd
_read:
;bx=hand
pushad
mov ax,bx
mov esi,ph ;handlers in use
mov edx,phs
@@:
cmp [esi],ax
jz @f
add esi,2
dec edx
jnz @b
popad
jmp do_dos
@@:
;reading with a pack file!!
;must make sure we don't read past EOF
;ecx=MAX TO READ
mov eax,ecx
add eax,cpos
.if eax>csiz
mov ecx,csiz
sub ecx,cpos ;read what is left over (=0 if cpos=csiz)
.endif
mov [esp+6*4],ecx ;save into ecx
popad
pushfd
call [old_int21h]
;gotta fix cpos to ptr to proper location within file
.if carry?
or byte ptr[esp+12],1 ;set carry
.else
and byte ptr[esp+12],0feh ;clear carry
add cpos,eax
.endif
pop ds
iretd
_lseek:
;bx=hand
pushad
mov ax,bx
mov esi,ph ;handlers in use
mov ecx,phs
@@:
cmp [esi],ax
jz @f
add esi,2
dec ecx
jnz @b
popad
jmp do_dos
@@:
popad
;LSEEKing with a pack file!!
;convert CX:DX => EDX
shl ecx,16
mov cx,dx
mov edx,ecx
.if al==0
add edx,coff
.endif
.if al==1 ;FIX : v2.01 : greatly updated
.if edx & 80000000h ;neg?
add edx,cpos
add edx,coff
.if edx > cend || edx < coff
mov edx,coff
.endif
.else
add edx,cpos
add edx,coff
.if edx > cend || edx < coff
mov edx,cend
.endif
.endif
xor al,al
.endif
.if al==2 ;this is not allowed if edx>0 so I just ignore edx!!
add edx,cend
.if edx>cend || edx < coff
mov edx,cend
.endif
xor al,al
.endif
.if al>2 ;???
jmp badseek
.endif
mov ecx,edx
shr ecx,16 ;CX:DX
pushfd
call [old_int21h] ;DX:AX
;gotta fix eax to ptr to proper location within file
.if carry?
;ds,ret,cs,flg
badseek:
or byte ptr[esp+12],1 ;set carry
.else
; DX:AX -> EAX
shl edx,16
mov dx,ax
mov eax,edx
and byte ptr[esp+12],0feh ;clear carry
sub eax,coff
mov cpos,eax ;new pos
; EAX -> DX:AX
mov edx,eax
shr edx,16
.endif
pop ds
iretd
;in:
;ah=45h
;bx=handle
;out:
;ax=new handle
; NOTE: changing offset of one changes the other.